﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;

namespace QAToolsAddin {
    static class Settings {
        private const string Folder = "QAToolsAddin";
        private const string Filename = "user-settings";
        private static Dictionary<string, object> _settings;

        public static object GetParam(Form form, string name, object default_) {
            return GetParam(form.Name, name, default_);
        }

        public static string ApplicationDataDir {
            get {
                string folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).TrimEnd('\\') + '\\' + Folder;
                if (!Directory.Exists(folder))
                    Directory.CreateDirectory(folder);
                return folder;
            }
        }

        public static bool TryGetParam(string category, string name, out object value) {
            name = category + "-" + name;
            if (_settings == null) {
                _settings = (Dictionary<string, object>)LoadFromFile(Filename);
                AppDomain.CurrentDomain.ProcessExit += (sender, e) => SaveToFile(Filename, _settings);
            }
            if (_settings == null)
                _settings = new Dictionary<string, object>();
            if (_settings.ContainsKey(name)) {
                value = _settings[name];
                return true;
            }
            value = null;
            return false;
        }

        public static object GetParam(string category, string name, object default_) {
            name = category + "-" + name;
            if (_settings == null) {
                _settings = (Dictionary<string, object>)LoadFromFile(Filename);
                AppDomain.CurrentDomain.ProcessExit += (sender, e) => SaveToFile(Filename, _settings);
            }
            if (_settings == null) {
                _settings = new Dictionary<string, object>();
                return default_;
            }
            if (_settings.ContainsKey(name))
                return _settings[name];
            return default_;
        }

        public static void SetParam(Form form, string name, object value) {
            SetParam(form.Name, name, value);
        }

        public static void SetParam(string category, string name, object value) {
            name = category + "-" + name;
            if (_settings == null)
                _settings = (Dictionary<string, object>)LoadFromFile(Filename);
            if (_settings == null)
                _settings = new Dictionary<string, object>();
            if (_settings.ContainsKey(name))
                _settings[name] = value;
            else
                _settings.Add(name, value);
        }

        private static void SaveToFile(string file_name, object data) {
            try {
                string appDataDir = ApplicationDataDir;
                if (!Directory.Exists(appDataDir)) {
                    Directory.CreateDirectory(appDataDir);
                }
                using (Stream stream = File.Open(appDataDir + "\\" + file_name, FileMode.Create)) {
                    var bformatter = new BinaryFormatter();
                    bformatter.Serialize(stream, data);
                    stream.Close();
                }
            } catch (Exception ex) {
                throw new Exception("Failed to load settings!", ex);
            }
        }

        private static object LoadFromFile(string name) {
            try {
                string appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).TrimEnd('\\') + '\\' + Folder;
                if (!File.Exists(appDataDir + "\\" + name)) {
                    return null;
                }
                object data;
                using (Stream stream = File.Open(appDataDir + "\\" + name, FileMode.Open)) {
                    var bformatter = new BinaryFormatter();
                    data = bformatter.Deserialize(stream);
                    stream.Close();
                }
                return data;
            } catch (Exception) {
                return null;
            }
        }

    }
}
